use crate::core::base_node::NodeStatus;
use crate::core::action;
use core::base_node::{BaseNode, NodeData, TBaseNode, BLACKBOARD_MEM_RUNNING_CHILD};
use core::behavior_tree::NodeTypeRegister;
use std::collections::HashMap;
use core::tick::Tick;

pub struct MemPriority {
    base_node: NodeData<BaseNode>,
    children: Vec<Box<TBaseNode>>
}
impl MemPriority {
    fn new(config: serde_json::Value)->Result<MemPriority, String> {
        match BaseNode::new(config) {
            Ok(_n) => {
                Ok(MemPriority {
                    base_node: NodeData::new(_n),
                    children: Vec::new()
                })
            }
            Err(_e) => {
                Err(_e)
            }
        }
    }
    pub fn register(container: &mut NodeTypeRegister, name: String) {
        container.register_type(name, Box::new(|config: serde_json::Value, nodes: &mut HashMap<String, Box<dyn TBaseNode>>| {
            match MemPriority::new(config) {
                Ok(_n) => {
                    nodes.insert(_n.base_node.id.to_string(), Box::new(_n));
                }
                Err(_e) => {}
            };
        }));
    }
}
impl TBaseNode for MemPriority {
    fn get_base_node_ref(&self) -> NodeData<BaseNode> {
        self.base_node.clone()
    }
    fn add_child(&mut self, child: Box<TBaseNode>) {
        self.children.push(child)
    }
    fn execute(&self, tick: &mut Tick) -> NodeStatus {
        BaseNode::_execute(self.base_node.clone(), tick, self)
    }
    fn open(&self, tick: &mut Tick) {
        tick.blackboard.set(&*BLACKBOARD_MEM_RUNNING_CHILD,  json!(0), &tick.tree.id, &self.base_node.id);
    }
    fn tick(&self, tick: &mut Tick) -> NodeStatus {
        let child = match tick.blackboard.get(&*BLACKBOARD_MEM_RUNNING_CHILD, &tick.tree.id, &self.base_node.id) {
            Some(_j) => {
                match _j.as_u64() {
                    Some(_t) => {
                        _t
                    }
                    None => { 0 }
                }
            }
            None => { 0 }
        };
        unsafe {
            for index in child as usize..self.children.len() {
                let child: &Box<dyn TBaseNode> = self.children.get_unchecked(index);
                let status = child.execute(tick);
                if status != NodeStatus::FAILURE {
                    if status == NodeStatus::RUNNING {
                        tick.blackboard.set(&*BLACKBOARD_MEM_RUNNING_CHILD, json!(index), &tick.tree.id, &self.base_node.id);
                    }
                    return status;
                }
            }
        }
        NodeStatus::FAILURE
    }
}